package middleware

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"gspeed/app/dist"
	"gspeed/app/utils"
	"gspeed/app/utils/email"
	"gspeed/app/utils/response"
	"gspeed/bootstrap/global"
	"net/http"
	"runtime/debug"
	"strings"
	"time"
)

func PanicMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		defer func() {
			if err := recover(); err != nil {
				errMsg := fmt.Sprintf("%s", err)
				errKey := utils.Md5("panic_" + errMsg)
				localDate, cacheGetErr := global.LocalCache.Get(errKey)
				if cacheGetErr != nil {
					global.Logger.Errorf("本地缓存获取出错：%s ", cacheGetErr.Error())
				}
				if localDate == nil {
					cacheErr := global.LocalCache.Set(errKey, []byte(errMsg))
					if cacheErr != nil {
						global.Logger.Errorf("本地缓存存储出错：%s ", cacheErr.Error())
					}
					panicHandler(c, err)
				}

			}
		}()

		c.Next()
	}
}

func panicHandler(c *gin.Context, err interface{}) {
	DebugStack := ""
	for _, line := range strings.Split(string(debug.Stack()), "\n") {
		DebugStack += line + "<br>"
	}
	subject := fmt.Sprintf(
		"【重要错误】%s 项目出错了！",
		global.Config.GetString("app.name"))
	body := strings.ReplaceAll(
		email.PanicTemplate,
		"{ErrorMsg}",
		fmt.Sprintf("%s", err))
	body = strings.ReplaceAll(
		body,
		"{RequestTime}",
		time.Now().Format("20060102 15:04:05 "))
	body = strings.ReplaceAll(
		body,
		"{RequestURL}",
		c.Request.Method+" "+c.Request.Host+c.Request.RequestURI)
	body = strings.ReplaceAll(
		body,
		"{RequestUA}",
		c.Request.UserAgent())
	body = strings.ReplaceAll(
		body,
		"{RequestIP}",
		c.ClientIP())
	body = strings.ReplaceAll(
		body,
		"{DebugStack}",
		DebugStack)

	// 发送邮件
	go email.Email.SendHtml(
		global.Config.GetStringSlice("email.Maintainer"),
		global.Config.GetString("app.name"),
		subject,
		body)

	// 记录日志
	go global.Logger.Errorf(
		"错误信息： %s; 请求时间： %s; 请求地址：%s; 请求UA：%s; 请求IP：%s; DebugStack：%s;",
		err,
		time.Now().Format("20060102 15:04:05 "),
		c.Request.Method+" "+c.Request.Host+c.Request.RequestURI,
		c.Request.UserAgent(),
		c.ClientIP(),
		DebugStack)
	// 返回信息给客户端
	response.Err(
		c,
		response.WithHttpStatus(http.StatusInternalServerError),
		response.WithCode(dist.MessageSystemError),
	)

}
